//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2024 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
@_spi(SotoInternal) import SotoCore

extension SavingsPlans {
    // MARK: Enums

    public enum CurrencyCode: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case cny = "CNY"
        case usd = "USD"
        public var description: String { return self.rawValue }
    }

    public enum SavingsPlanOfferingFilterAttribute: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case instanceFamily = "instanceFamily"
        case region = "region"
        public var description: String { return self.rawValue }
    }

    public enum SavingsPlanOfferingPropertyKey: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case instanceFamily = "instanceFamily"
        case region = "region"
        public var description: String { return self.rawValue }
    }

    public enum SavingsPlanPaymentOption: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case allUpfront = "All Upfront"
        case noUpfront = "No Upfront"
        case partialUpfront = "Partial Upfront"
        public var description: String { return self.rawValue }
    }

    public enum SavingsPlanProductType: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case ec2 = "EC2"
        case fargate = "Fargate"
        case lambda = "Lambda"
        case sagemaker = "SageMaker"
        public var description: String { return self.rawValue }
    }

    public enum SavingsPlanRateFilterAttribute: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case instanceFamily = "instanceFamily"
        case instanceType = "instanceType"
        case productDescription = "productDescription"
        case productId = "productId"
        case region = "region"
        case tenancy = "tenancy"
        public var description: String { return self.rawValue }
    }

    public enum SavingsPlanRateFilterName: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case instanceType = "instanceType"
        case operation = "operation"
        case productDescription = "productDescription"
        case productType = "productType"
        case region = "region"
        case serviceCode = "serviceCode"
        case tenancy = "tenancy"
        case usageType = "usageType"
        public var description: String { return self.rawValue }
    }

    public enum SavingsPlanRatePropertyKey: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case instanceFamily = "instanceFamily"
        case instanceType = "instanceType"
        case productDescription = "productDescription"
        case region = "region"
        case tenancy = "tenancy"
        public var description: String { return self.rawValue }
    }

    public enum SavingsPlanRateServiceCode: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case ec2 = "AmazonEC2"
        case fargate = "AmazonECS"
        case fargateEks = "AmazonEKS"
        case lambda = "AWSLambda"
        case sagemaker = "AmazonSageMaker"
        public var description: String { return self.rawValue }
    }

    public enum SavingsPlanRateUnit: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case hours = "Hrs"
        case lambdaGbSecond = "Lambda-GB-Second"
        case request = "Request"
        public var description: String { return self.rawValue }
    }

    public enum SavingsPlanState: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case active = "active"
        case paymentFailed = "payment-failed"
        case paymentPending = "payment-pending"
        case pendingReturn = "pending-return"
        case queued = "queued"
        case queuedDeleted = "queued-deleted"
        case retired = "retired"
        case returned = "returned"
        public var description: String { return self.rawValue }
    }

    public enum SavingsPlanType: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case compute = "Compute"
        case ec2Instance = "EC2Instance"
        case sagemaker = "SageMaker"
        public var description: String { return self.rawValue }
    }

    public enum SavingsPlansFilterName: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case commitment = "commitment"
        case ec2InstanceFamily = "ec2-instance-family"
        case end = "end"
        case paymentOption = "payment-option"
        case region = "region"
        case savingsPlanType = "savings-plan-type"
        case start = "start"
        case term = "term"
        case upfront = "upfront"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct CreateSavingsPlanRequest: AWSEncodableShape {
        /// A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.
        public let clientToken: String?
        /// The hourly commitment, in the same currency of the savingsPlanOfferingId. This is a value between 0.001 and 1 million. You cannot specify more than five digits after the decimal point.
        public let commitment: String
        /// The purchase time of the Savings Plan in UTC format (YYYY-MM-DDTHH:MM:SSZ).
        public let purchaseTime: Date?
        /// The ID of the offering.
        public let savingsPlanOfferingId: String
        /// One or more tags.
        public let tags: [String: String]?
        /// The up-front payment amount. This is a whole number between 50 and 99 percent of the total value of the Savings Plan. This parameter is only supported if the payment option is Partial Upfront.
        public let upfrontPaymentAmount: String?

        @inlinable
        public init(clientToken: String? = CreateSavingsPlanRequest.idempotencyToken(), commitment: String, purchaseTime: Date? = nil, savingsPlanOfferingId: String, tags: [String: String]? = nil, upfrontPaymentAmount: String? = nil) {
            self.clientToken = clientToken
            self.commitment = commitment
            self.purchaseTime = purchaseTime
            self.savingsPlanOfferingId = savingsPlanOfferingId
            self.tags = tags
            self.upfrontPaymentAmount = upfrontPaymentAmount
        }

        private enum CodingKeys: String, CodingKey {
            case clientToken = "clientToken"
            case commitment = "commitment"
            case purchaseTime = "purchaseTime"
            case savingsPlanOfferingId = "savingsPlanOfferingId"
            case tags = "tags"
            case upfrontPaymentAmount = "upfrontPaymentAmount"
        }
    }

    public struct CreateSavingsPlanResponse: AWSDecodableShape {
        /// The ID of the Savings Plan.
        public let savingsPlanId: String?

        @inlinable
        public init(savingsPlanId: String? = nil) {
            self.savingsPlanId = savingsPlanId
        }

        private enum CodingKeys: String, CodingKey {
            case savingsPlanId = "savingsPlanId"
        }
    }

    public struct DeleteQueuedSavingsPlanRequest: AWSEncodableShape {
        /// The ID of the Savings Plan.
        public let savingsPlanId: String

        @inlinable
        public init(savingsPlanId: String) {
            self.savingsPlanId = savingsPlanId
        }

        private enum CodingKeys: String, CodingKey {
            case savingsPlanId = "savingsPlanId"
        }
    }

    public struct DeleteQueuedSavingsPlanResponse: AWSDecodableShape {
        public init() {}
    }

    public struct DescribeSavingsPlanRatesRequest: AWSEncodableShape {
        /// The filters.
        public let filters: [SavingsPlanRateFilter]?
        /// The maximum number of results to return with a single call. To retrieve additional results, make another call with the returned token value.
        public let maxResults: Int?
        /// The token for the next page of results.
        public let nextToken: String?
        /// The ID of the Savings Plan.
        public let savingsPlanId: String

        @inlinable
        public init(filters: [SavingsPlanRateFilter]? = nil, maxResults: Int? = nil, nextToken: String? = nil, savingsPlanId: String) {
            self.filters = filters
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.savingsPlanId = savingsPlanId
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 1000)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: "^[A-Za-z0-9/=\\+]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case filters = "filters"
            case maxResults = "maxResults"
            case nextToken = "nextToken"
            case savingsPlanId = "savingsPlanId"
        }
    }

    public struct DescribeSavingsPlanRatesResponse: AWSDecodableShape {
        /// The token to use to retrieve the next page of results. This value is null when there are no more results to return.
        public let nextToken: String?
        /// The ID of the Savings Plan.
        public let savingsPlanId: String?
        /// Information about the Savings Plan rates.
        public let searchResults: [SavingsPlanRate]?

        @inlinable
        public init(nextToken: String? = nil, savingsPlanId: String? = nil, searchResults: [SavingsPlanRate]? = nil) {
            self.nextToken = nextToken
            self.savingsPlanId = savingsPlanId
            self.searchResults = searchResults
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken = "nextToken"
            case savingsPlanId = "savingsPlanId"
            case searchResults = "searchResults"
        }
    }

    public struct DescribeSavingsPlansOfferingRatesRequest: AWSEncodableShape {
        /// The filters.
        public let filters: [SavingsPlanOfferingRateFilterElement]?
        /// The maximum number of results to return with a single call. To retrieve additional results, make another call with the returned token value.
        public let maxResults: Int?
        /// The token for the next page of results.
        public let nextToken: String?
        /// The specific Amazon Web Services operation for the line item in the billing report.
        public let operations: [String]?
        /// The Amazon Web Services products.
        public let products: [SavingsPlanProductType]?
        /// The IDs of the offerings.
        public let savingsPlanOfferingIds: [String]?
        /// The payment options.
        public let savingsPlanPaymentOptions: [SavingsPlanPaymentOption]?
        /// The plan types.
        public let savingsPlanTypes: [SavingsPlanType]?
        /// The services.
        public let serviceCodes: [SavingsPlanRateServiceCode]?
        /// The usage details of the line item in the billing report.
        public let usageTypes: [String]?

        @inlinable
        public init(filters: [SavingsPlanOfferingRateFilterElement]? = nil, maxResults: Int? = nil, nextToken: String? = nil, operations: [String]? = nil, products: [SavingsPlanProductType]? = nil, savingsPlanOfferingIds: [String]? = nil, savingsPlanPaymentOptions: [SavingsPlanPaymentOption]? = nil, savingsPlanTypes: [SavingsPlanType]? = nil, serviceCodes: [SavingsPlanRateServiceCode]? = nil, usageTypes: [String]? = nil) {
            self.filters = filters
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.operations = operations
            self.products = products
            self.savingsPlanOfferingIds = savingsPlanOfferingIds
            self.savingsPlanPaymentOptions = savingsPlanPaymentOptions
            self.savingsPlanTypes = savingsPlanTypes
            self.serviceCodes = serviceCodes
            self.usageTypes = usageTypes
        }

        public func validate(name: String) throws {
            try self.filters?.forEach {
                try $0.validate(name: "\(name).filters[]")
            }
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 1000)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 0)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: "^[A-Za-z0-9/=\\+]+$")
            try self.operations?.forEach {
                try validate($0, name: "operations[]", parent: name, max: 255)
                try validate($0, name: "operations[]", parent: name, pattern: "^[a-zA-Z0-9_ \\/.:-]*$")
            }
            try self.savingsPlanOfferingIds?.forEach {
                try validate($0, name: "savingsPlanOfferingIds[]", parent: name, pattern: "^[a-f0-9]+(-[a-f0-9]+)*$")
            }
            try self.usageTypes?.forEach {
                try validate($0, name: "usageTypes[]", parent: name, max: 255)
                try validate($0, name: "usageTypes[]", parent: name, pattern: "^[a-zA-Z0-9_ \\/.:-]+$")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case filters = "filters"
            case maxResults = "maxResults"
            case nextToken = "nextToken"
            case operations = "operations"
            case products = "products"
            case savingsPlanOfferingIds = "savingsPlanOfferingIds"
            case savingsPlanPaymentOptions = "savingsPlanPaymentOptions"
            case savingsPlanTypes = "savingsPlanTypes"
            case serviceCodes = "serviceCodes"
            case usageTypes = "usageTypes"
        }
    }

    public struct DescribeSavingsPlansOfferingRatesResponse: AWSDecodableShape {
        /// The token to use to retrieve the next page of results. This value is null when there are no more results to return.
        public let nextToken: String?
        /// Information about the Savings Plans offering rates.
        public let searchResults: [SavingsPlanOfferingRate]?

        @inlinable
        public init(nextToken: String? = nil, searchResults: [SavingsPlanOfferingRate]? = nil) {
            self.nextToken = nextToken
            self.searchResults = searchResults
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken = "nextToken"
            case searchResults = "searchResults"
        }
    }

    public struct DescribeSavingsPlansOfferingsRequest: AWSEncodableShape {
        /// The currencies.
        public let currencies: [CurrencyCode]?
        /// The descriptions.
        public let descriptions: [String]?
        /// The duration, in seconds.
        public let durations: [Int64]?
        /// The filters.
        public let filters: [SavingsPlanOfferingFilterElement]?
        /// The maximum number of results to return with a single call. To retrieve additional results, make another call with the returned token value.
        public let maxResults: Int?
        /// The token for the next page of results.
        public let nextToken: String?
        /// The IDs of the offerings.
        public let offeringIds: [String]?
        /// The specific Amazon Web Services operation for the line item in the billing report.
        public let operations: [String]?
        /// The payment options.
        public let paymentOptions: [SavingsPlanPaymentOption]?
        /// The plan types.
        public let planTypes: [SavingsPlanType]?
        /// The product type.
        public let productType: SavingsPlanProductType?
        /// The services.
        public let serviceCodes: [String]?
        /// The usage details of the line item in the billing report.
        public let usageTypes: [String]?

        @inlinable
        public init(currencies: [CurrencyCode]? = nil, descriptions: [String]? = nil, durations: [Int64]? = nil, filters: [SavingsPlanOfferingFilterElement]? = nil, maxResults: Int? = nil, nextToken: String? = nil, offeringIds: [String]? = nil, operations: [String]? = nil, paymentOptions: [SavingsPlanPaymentOption]? = nil, planTypes: [SavingsPlanType]? = nil, productType: SavingsPlanProductType? = nil, serviceCodes: [String]? = nil, usageTypes: [String]? = nil) {
            self.currencies = currencies
            self.descriptions = descriptions
            self.durations = durations
            self.filters = filters
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.offeringIds = offeringIds
            self.operations = operations
            self.paymentOptions = paymentOptions
            self.planTypes = planTypes
            self.productType = productType
            self.serviceCodes = serviceCodes
            self.usageTypes = usageTypes
        }

        public func validate(name: String) throws {
            try self.descriptions?.forEach {
                try validate($0, name: "descriptions[]", parent: name, pattern: "^[a-zA-Z0-9_\\- ]+$")
            }
            try self.durations?.forEach {
                try validate($0, name: "durations[]", parent: name, min: 0)
            }
            try self.filters?.forEach {
                try $0.validate(name: "\(name).filters[]")
            }
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 1000)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 0)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: "^[A-Za-z0-9/=\\+]+$")
            try self.offeringIds?.forEach {
                try validate($0, name: "offeringIds[]", parent: name, pattern: "^[a-f0-9]+(-[a-f0-9]+)*$")
            }
            try self.operations?.forEach {
                try validate($0, name: "operations[]", parent: name, max: 255)
                try validate($0, name: "operations[]", parent: name, pattern: "^[a-zA-Z0-9_ \\/.:-]*$")
            }
            try self.serviceCodes?.forEach {
                try validate($0, name: "serviceCodes[]", parent: name, max: 255)
                try validate($0, name: "serviceCodes[]", parent: name, pattern: "^[a-zA-Z]+$")
            }
            try self.usageTypes?.forEach {
                try validate($0, name: "usageTypes[]", parent: name, max: 255)
                try validate($0, name: "usageTypes[]", parent: name, pattern: "^[a-zA-Z0-9_ \\/.:-]+$")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case currencies = "currencies"
            case descriptions = "descriptions"
            case durations = "durations"
            case filters = "filters"
            case maxResults = "maxResults"
            case nextToken = "nextToken"
            case offeringIds = "offeringIds"
            case operations = "operations"
            case paymentOptions = "paymentOptions"
            case planTypes = "planTypes"
            case productType = "productType"
            case serviceCodes = "serviceCodes"
            case usageTypes = "usageTypes"
        }
    }

    public struct DescribeSavingsPlansOfferingsResponse: AWSDecodableShape {
        /// The token to use to retrieve the next page of results. This value is null when there are no more results to return.
        public let nextToken: String?
        /// Information about the Savings Plans offerings.
        public let searchResults: [SavingsPlanOffering]?

        @inlinable
        public init(nextToken: String? = nil, searchResults: [SavingsPlanOffering]? = nil) {
            self.nextToken = nextToken
            self.searchResults = searchResults
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken = "nextToken"
            case searchResults = "searchResults"
        }
    }

    public struct DescribeSavingsPlansRequest: AWSEncodableShape {
        /// The filters.
        public let filters: [SavingsPlanFilter]?
        /// The maximum number of results to return with a single call. To retrieve additional results, make another call with the returned token value.
        public let maxResults: Int?
        /// The token for the next page of results.
        public let nextToken: String?
        /// The Amazon Resource Names (ARN) of the Savings Plans.
        public let savingsPlanArns: [String]?
        /// The IDs of the Savings Plans.
        public let savingsPlanIds: [String]?
        /// The current states of the Savings Plans.
        public let states: [SavingsPlanState]?

        @inlinable
        public init(filters: [SavingsPlanFilter]? = nil, maxResults: Int? = nil, nextToken: String? = nil, savingsPlanArns: [String]? = nil, savingsPlanIds: [String]? = nil, states: [SavingsPlanState]? = nil) {
            self.filters = filters
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.savingsPlanArns = savingsPlanArns
            self.savingsPlanIds = savingsPlanIds
            self.states = states
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 1000)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: "^[A-Za-z0-9/=\\+]+$")
            try self.savingsPlanArns?.forEach {
                try validate($0, name: "savingsPlanArns[]", parent: name, pattern: "^arn:aws:[a-z]+:([a-z]{2}-[a-z]+-\\d{1}|):(\\d{12}):savingsplan\\/([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})$")
            }
            try self.validate(self.savingsPlanArns, name: "savingsPlanArns", parent: name, max: 100)
        }

        private enum CodingKeys: String, CodingKey {
            case filters = "filters"
            case maxResults = "maxResults"
            case nextToken = "nextToken"
            case savingsPlanArns = "savingsPlanArns"
            case savingsPlanIds = "savingsPlanIds"
            case states = "states"
        }
    }

    public struct DescribeSavingsPlansResponse: AWSDecodableShape {
        /// The token to use to retrieve the next page of results. This value is null when there are no more results to return.
        public let nextToken: String?
        /// Information about the Savings Plans.
        public let savingsPlans: [SavingsPlan]?

        @inlinable
        public init(nextToken: String? = nil, savingsPlans: [SavingsPlan]? = nil) {
            self.nextToken = nextToken
            self.savingsPlans = savingsPlans
        }

        private enum CodingKeys: String, CodingKey {
            case nextToken = "nextToken"
            case savingsPlans = "savingsPlans"
        }
    }

    public struct ListTagsForResourceRequest: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the resource.
        public let resourceArn: String

        @inlinable
        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws:[a-z]+:([a-z]{2}-[a-z]+-\\d{1}|):(\\d{12}):savingsplan\\/([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})$")
        }

        private enum CodingKeys: String, CodingKey {
            case resourceArn = "resourceArn"
        }
    }

    public struct ListTagsForResourceResponse: AWSDecodableShape {
        /// Information about the tags.
        public let tags: [String: String]?

        @inlinable
        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "tags"
        }
    }

    public struct ParentSavingsPlanOffering: AWSDecodableShape {
        /// The currency.
        public let currency: CurrencyCode?
        /// The duration, in seconds.
        public let durationSeconds: Int64?
        /// The ID of the offering.
        public let offeringId: String?
        /// The payment option.
        public let paymentOption: SavingsPlanPaymentOption?
        /// The description.
        public let planDescription: String?
        /// The plan type.
        public let planType: SavingsPlanType?

        @inlinable
        public init(currency: CurrencyCode? = nil, durationSeconds: Int64? = nil, offeringId: String? = nil, paymentOption: SavingsPlanPaymentOption? = nil, planDescription: String? = nil, planType: SavingsPlanType? = nil) {
            self.currency = currency
            self.durationSeconds = durationSeconds
            self.offeringId = offeringId
            self.paymentOption = paymentOption
            self.planDescription = planDescription
            self.planType = planType
        }

        private enum CodingKeys: String, CodingKey {
            case currency = "currency"
            case durationSeconds = "durationSeconds"
            case offeringId = "offeringId"
            case paymentOption = "paymentOption"
            case planDescription = "planDescription"
            case planType = "planType"
        }
    }

    public struct ReturnSavingsPlanRequest: AWSEncodableShape {
        /// A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.
        public let clientToken: String?
        /// The ID of the Savings Plan.
        public let savingsPlanId: String

        @inlinable
        public init(clientToken: String? = ReturnSavingsPlanRequest.idempotencyToken(), savingsPlanId: String) {
            self.clientToken = clientToken
            self.savingsPlanId = savingsPlanId
        }

        private enum CodingKeys: String, CodingKey {
            case clientToken = "clientToken"
            case savingsPlanId = "savingsPlanId"
        }
    }

    public struct ReturnSavingsPlanResponse: AWSDecodableShape {
        /// The ID of the Savings Plan.
        public let savingsPlanId: String?

        @inlinable
        public init(savingsPlanId: String? = nil) {
            self.savingsPlanId = savingsPlanId
        }

        private enum CodingKeys: String, CodingKey {
            case savingsPlanId = "savingsPlanId"
        }
    }

    public struct SavingsPlan: AWSDecodableShape {
        /// The hourly commitment amount in the specified currency.
        public let commitment: String?
        /// The currency.
        public let currency: CurrencyCode?
        /// The description.
        public let description: String?
        /// The EC2 instance family.
        public let ec2InstanceFamily: String?
        /// The end time.
        public let end: String?
        /// The ID of the offering.
        public let offeringId: String?
        /// The payment option.
        public let paymentOption: SavingsPlanPaymentOption?
        /// The product types.
        public let productTypes: [SavingsPlanProductType]?
        /// The recurring payment amount.
        public let recurringPaymentAmount: String?
        /// The Amazon Web Services Region.
        public let region: String?
        /// The time until when a return for the Savings Plan can be requested. If the Savings Plan is not returnable, the field reflects the Savings Plan start time.
        public let returnableUntil: String?
        /// The Amazon Resource Name (ARN) of the Savings Plan.
        public let savingsPlanArn: String?
        /// The ID of the Savings Plan.
        public let savingsPlanId: String?
        /// The plan type.
        public let savingsPlanType: SavingsPlanType?
        /// The start time.
        public let start: String?
        /// The current state.
        public let state: SavingsPlanState?
        /// One or more tags.
        public let tags: [String: String]?
        /// The duration of the term, in seconds.
        public let termDurationInSeconds: Int64?
        /// The up-front payment amount.
        public let upfrontPaymentAmount: String?

        @inlinable
        public init(commitment: String? = nil, currency: CurrencyCode? = nil, description: String? = nil, ec2InstanceFamily: String? = nil, end: String? = nil, offeringId: String? = nil, paymentOption: SavingsPlanPaymentOption? = nil, productTypes: [SavingsPlanProductType]? = nil, recurringPaymentAmount: String? = nil, region: String? = nil, returnableUntil: String? = nil, savingsPlanArn: String? = nil, savingsPlanId: String? = nil, savingsPlanType: SavingsPlanType? = nil, start: String? = nil, state: SavingsPlanState? = nil, tags: [String: String]? = nil, termDurationInSeconds: Int64? = nil, upfrontPaymentAmount: String? = nil) {
            self.commitment = commitment
            self.currency = currency
            self.description = description
            self.ec2InstanceFamily = ec2InstanceFamily
            self.end = end
            self.offeringId = offeringId
            self.paymentOption = paymentOption
            self.productTypes = productTypes
            self.recurringPaymentAmount = recurringPaymentAmount
            self.region = region
            self.returnableUntil = returnableUntil
            self.savingsPlanArn = savingsPlanArn
            self.savingsPlanId = savingsPlanId
            self.savingsPlanType = savingsPlanType
            self.start = start
            self.state = state
            self.tags = tags
            self.termDurationInSeconds = termDurationInSeconds
            self.upfrontPaymentAmount = upfrontPaymentAmount
        }

        private enum CodingKeys: String, CodingKey {
            case commitment = "commitment"
            case currency = "currency"
            case description = "description"
            case ec2InstanceFamily = "ec2InstanceFamily"
            case end = "end"
            case offeringId = "offeringId"
            case paymentOption = "paymentOption"
            case productTypes = "productTypes"
            case recurringPaymentAmount = "recurringPaymentAmount"
            case region = "region"
            case returnableUntil = "returnableUntil"
            case savingsPlanArn = "savingsPlanArn"
            case savingsPlanId = "savingsPlanId"
            case savingsPlanType = "savingsPlanType"
            case start = "start"
            case state = "state"
            case tags = "tags"
            case termDurationInSeconds = "termDurationInSeconds"
            case upfrontPaymentAmount = "upfrontPaymentAmount"
        }
    }

    public struct SavingsPlanFilter: AWSEncodableShape {
        /// The filter name.
        public let name: SavingsPlansFilterName?
        /// The filter value.
        public let values: [String]?

        @inlinable
        public init(name: SavingsPlansFilterName? = nil, values: [String]? = nil) {
            self.name = name
            self.values = values
        }

        private enum CodingKeys: String, CodingKey {
            case name = "name"
            case values = "values"
        }
    }

    public struct SavingsPlanOffering: AWSDecodableShape {
        /// The currency.
        public let currency: CurrencyCode?
        /// The description.
        public let description: String?
        /// The duration, in seconds.
        public let durationSeconds: Int64?
        /// The ID of the offering.
        public let offeringId: String?
        /// The specific Amazon Web Services operation for the line item in the billing report.
        public let operation: String?
        /// The payment option.
        public let paymentOption: SavingsPlanPaymentOption?
        /// The plan type.
        public let planType: SavingsPlanType?
        /// The product type.
        public let productTypes: [SavingsPlanProductType]?
        /// The properties.
        public let properties: [SavingsPlanOfferingProperty]?
        /// The service.
        public let serviceCode: String?
        /// The usage details of the line item in the billing report.
        public let usageType: String?

        @inlinable
        public init(currency: CurrencyCode? = nil, description: String? = nil, durationSeconds: Int64? = nil, offeringId: String? = nil, operation: String? = nil, paymentOption: SavingsPlanPaymentOption? = nil, planType: SavingsPlanType? = nil, productTypes: [SavingsPlanProductType]? = nil, properties: [SavingsPlanOfferingProperty]? = nil, serviceCode: String? = nil, usageType: String? = nil) {
            self.currency = currency
            self.description = description
            self.durationSeconds = durationSeconds
            self.offeringId = offeringId
            self.operation = operation
            self.paymentOption = paymentOption
            self.planType = planType
            self.productTypes = productTypes
            self.properties = properties
            self.serviceCode = serviceCode
            self.usageType = usageType
        }

        private enum CodingKeys: String, CodingKey {
            case currency = "currency"
            case description = "description"
            case durationSeconds = "durationSeconds"
            case offeringId = "offeringId"
            case operation = "operation"
            case paymentOption = "paymentOption"
            case planType = "planType"
            case productTypes = "productTypes"
            case properties = "properties"
            case serviceCode = "serviceCode"
            case usageType = "usageType"
        }
    }

    public struct SavingsPlanOfferingFilterElement: AWSEncodableShape {
        /// The filter name.
        public let name: SavingsPlanOfferingFilterAttribute?
        /// The filter values.
        public let values: [String]?

        @inlinable
        public init(name: SavingsPlanOfferingFilterAttribute? = nil, values: [String]? = nil) {
            self.name = name
            self.values = values
        }

        public func validate(name: String) throws {
            try self.values?.forEach {
                try validate($0, name: "values[]", parent: name, pattern: "^[a-zA-Z0-9_ \\/.\\:\\-\\(\\)]+$")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case name = "name"
            case values = "values"
        }
    }

    public struct SavingsPlanOfferingProperty: AWSDecodableShape {
        /// The property name.
        public let name: SavingsPlanOfferingPropertyKey?
        /// The property value.
        public let value: String?

        @inlinable
        public init(name: SavingsPlanOfferingPropertyKey? = nil, value: String? = nil) {
            self.name = name
            self.value = value
        }

        private enum CodingKeys: String, CodingKey {
            case name = "name"
            case value = "value"
        }
    }

    public struct SavingsPlanOfferingRate: AWSDecodableShape {
        /// The specific Amazon Web Services operation for the line item in the billing report.
        public let operation: String?
        /// The product type.
        public let productType: SavingsPlanProductType?
        /// The properties.
        public let properties: [SavingsPlanOfferingRateProperty]?
        /// The Savings Plan rate.
        public let rate: String?
        /// The Savings Plan offering.
        public let savingsPlanOffering: ParentSavingsPlanOffering?
        /// The service.
        public let serviceCode: SavingsPlanRateServiceCode?
        /// The unit.
        public let unit: SavingsPlanRateUnit?
        /// The usage details of the line item in the billing report.
        public let usageType: String?

        @inlinable
        public init(operation: String? = nil, productType: SavingsPlanProductType? = nil, properties: [SavingsPlanOfferingRateProperty]? = nil, rate: String? = nil, savingsPlanOffering: ParentSavingsPlanOffering? = nil, serviceCode: SavingsPlanRateServiceCode? = nil, unit: SavingsPlanRateUnit? = nil, usageType: String? = nil) {
            self.operation = operation
            self.productType = productType
            self.properties = properties
            self.rate = rate
            self.savingsPlanOffering = savingsPlanOffering
            self.serviceCode = serviceCode
            self.unit = unit
            self.usageType = usageType
        }

        private enum CodingKeys: String, CodingKey {
            case operation = "operation"
            case productType = "productType"
            case properties = "properties"
            case rate = "rate"
            case savingsPlanOffering = "savingsPlanOffering"
            case serviceCode = "serviceCode"
            case unit = "unit"
            case usageType = "usageType"
        }
    }

    public struct SavingsPlanOfferingRateFilterElement: AWSEncodableShape {
        /// The filter name.
        public let name: SavingsPlanRateFilterAttribute?
        /// The filter values.
        public let values: [String]?

        @inlinable
        public init(name: SavingsPlanRateFilterAttribute? = nil, values: [String]? = nil) {
            self.name = name
            self.values = values
        }

        public func validate(name: String) throws {
            try self.values?.forEach {
                try validate($0, name: "values[]", parent: name, pattern: "^[a-zA-Z0-9_ \\/.\\:\\-\\(\\)]+$")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case name = "name"
            case values = "values"
        }
    }

    public struct SavingsPlanOfferingRateProperty: AWSDecodableShape {
        /// The property name.
        public let name: String?
        /// The property value.
        public let value: String?

        @inlinable
        public init(name: String? = nil, value: String? = nil) {
            self.name = name
            self.value = value
        }

        private enum CodingKeys: String, CodingKey {
            case name = "name"
            case value = "value"
        }
    }

    public struct SavingsPlanRate: AWSDecodableShape {
        /// The currency.
        public let currency: CurrencyCode?
        /// The specific Amazon Web Services operation for the line item in the billing report.
        public let operation: String?
        /// The product type.
        public let productType: SavingsPlanProductType?
        /// The properties.
        public let properties: [SavingsPlanRateProperty]?
        /// The rate.
        public let rate: String?
        /// The service.
        public let serviceCode: SavingsPlanRateServiceCode?
        /// The unit.
        public let unit: SavingsPlanRateUnit?
        /// The usage details of the line item in the billing report.
        public let usageType: String?

        @inlinable
        public init(currency: CurrencyCode? = nil, operation: String? = nil, productType: SavingsPlanProductType? = nil, properties: [SavingsPlanRateProperty]? = nil, rate: String? = nil, serviceCode: SavingsPlanRateServiceCode? = nil, unit: SavingsPlanRateUnit? = nil, usageType: String? = nil) {
            self.currency = currency
            self.operation = operation
            self.productType = productType
            self.properties = properties
            self.rate = rate
            self.serviceCode = serviceCode
            self.unit = unit
            self.usageType = usageType
        }

        private enum CodingKeys: String, CodingKey {
            case currency = "currency"
            case operation = "operation"
            case productType = "productType"
            case properties = "properties"
            case rate = "rate"
            case serviceCode = "serviceCode"
            case unit = "unit"
            case usageType = "usageType"
        }
    }

    public struct SavingsPlanRateFilter: AWSEncodableShape {
        /// The filter name.
        public let name: SavingsPlanRateFilterName?
        /// The filter values.
        public let values: [String]?

        @inlinable
        public init(name: SavingsPlanRateFilterName? = nil, values: [String]? = nil) {
            self.name = name
            self.values = values
        }

        private enum CodingKeys: String, CodingKey {
            case name = "name"
            case values = "values"
        }
    }

    public struct SavingsPlanRateProperty: AWSDecodableShape {
        /// The property name.
        public let name: SavingsPlanRatePropertyKey?
        /// The property value.
        public let value: String?

        @inlinable
        public init(name: SavingsPlanRatePropertyKey? = nil, value: String? = nil) {
            self.name = name
            self.value = value
        }

        private enum CodingKeys: String, CodingKey {
            case name = "name"
            case value = "value"
        }
    }

    public struct TagResourceRequest: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the resource.
        public let resourceArn: String
        /// One or more tags. For example, { "tags": {"key1":"value1", "key2":"value2"} }.
        public let tags: [String: String]

        @inlinable
        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws:[a-z]+:([a-z]{2}-[a-z]+-\\d{1}|):(\\d{12}):savingsplan\\/([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})$")
        }

        private enum CodingKeys: String, CodingKey {
            case resourceArn = "resourceArn"
            case tags = "tags"
        }
    }

    public struct TagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UntagResourceRequest: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the resource.
        public let resourceArn: String
        /// The tag keys.
        public let tagKeys: [String]

        @inlinable
        public init(resourceArn: String, tagKeys: [String]) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws:[a-z]+:([a-z]{2}-[a-z]+-\\d{1}|):(\\d{12}):savingsplan\\/([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})$")
        }

        private enum CodingKeys: String, CodingKey {
            case resourceArn = "resourceArn"
            case tagKeys = "tagKeys"
        }
    }

    public struct UntagResourceResponse: AWSDecodableShape {
        public init() {}
    }
}

// MARK: - Errors

/// Error enum for SavingsPlans
public struct SavingsPlansErrorType: AWSErrorType {
    enum Code: String {
        case internalServerException = "InternalServerException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize SavingsPlans
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// An unexpected error occurred.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// The specified resource was not found.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// A service quota has been exceeded.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    /// One of the input parameters is not valid.
    public static var validationException: Self { .init(.validationException) }
}

extension SavingsPlansErrorType: Equatable {
    public static func == (lhs: SavingsPlansErrorType, rhs: SavingsPlansErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension SavingsPlansErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
